﻿// -----------------------------------------------------------------------
//    This file is part of TSGE.
//
//    TSGE is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 2 of the License, or
//    (at your option) any later version.
//
//    TSGE is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with TSGE.  If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Controls;
using System.Windows.Media.Imaging;

namespace tsge.Controls
{
    /// <summary>
    /// Interaction logic for ModelViewer.xaml
    /// 
    ///     Inherits:
    ///         UserControl
    /// </summary>
    public partial class ModelViewer : UserControl
    {
        /// <summary>
        /// Internal copy of the texture shading colors.
        /// </summary>
        private System.Windows.Media.Color m_vEyeColor;
        private System.Windows.Media.Color m_vEyeWhitesColor;
        private System.Windows.Media.Color m_vHairColor;
        private System.Windows.Media.Color m_vHandsColor;
        private System.Windows.Media.Color m_vHeadColor;
        private System.Windows.Media.Color m_vPantsColor;
        private System.Windows.Media.Color m_vShirtColor;
        private System.Windows.Media.Color m_vShoesColor;
        private System.Windows.Media.Color m_vUnderShirtColor;

        /// <summary>
        /// Internal copy of the texture image paths.
        /// </summary>
        private String m_vEyeFile;
        private String m_vEyeWhitesFile;
        private String m_vHairFile;
        private String m_vHandsFile;
        private String m_vHeadFile;
        private String m_vPantsFile;
        private String m_vShirtFile;
        private String m_vShoesFile;
        private String m_vUnderShirtFile;

        /// <summary>
        /// Internal copy of the image textures.
        /// </summary>
        private Bitmap m_vEyeTexture;
        private Bitmap m_vEyeWhitesTexture;
        private Bitmap m_vHairTexture;
        private Bitmap m_vHandsTexture;
        private Bitmap m_vHeadTexture;
        private Bitmap m_vPantsTexture;
        private Bitmap m_vShirtTexture;
        private Bitmap m_vShoesTexture;
        private Bitmap m_vUnderShirtTexture;

        /// <summary>
        /// Internal copy of the largest image dimensions.
        /// </summary>
        private static Int32 m_vLargestWidth = 0;
        private static Int32 m_vLargestHeight = 0;

        /// <summary>
        /// Default Constructor
        /// </summary>
        public ModelViewer()
        {
            InitializeComponent();

            this.m_vEyeFile = "Data\\Eyes\\eyes.png";
            this.m_vEyeColor = System.Windows.Media.Color.FromRgb(105, 90, 75);

            this.m_vEyeWhitesFile = "Data\\Eyes\\eye_whites.png";
            this.m_vEyeWhitesColor = System.Windows.Media.Color.FromRgb(255, 255, 255);

            this.m_vHairFile = "Data\\Hair\\hair_0.png";
            this.m_vHairColor = System.Windows.Media.Color.FromRgb(215, 90, 55);

            this.m_vHandsFile = "Data\\Hands\\hands.png";
            this.m_vHandsColor = System.Windows.Media.Color.FromRgb(255, 125, 75);

            this.m_vHeadFile = "Data\\Heads\\head.png";
            this.m_vHeadColor = System.Windows.Media.Color.FromRgb(255, 125, 75);

            this.m_vPantsFile = "Data\\Pants\\pants.png";
            this.m_vPantsColor = System.Windows.Media.Color.FromRgb(255, 230, 175);

            this.m_vShirtFile = "Data\\Shirts\\shirt.png";
            this.m_vShirtColor = System.Windows.Media.Color.FromRgb(175, 165, 140);

            this.m_vShoesFile = "Data\\Shoes\\shoes.png";
            this.m_vShoesColor = System.Windows.Media.Color.FromRgb(160, 106, 60);

            this.m_vUnderShirtFile = "Data\\UnderShirts\\undershirt.png";
            this.m_vUnderShirtColor = System.Windows.Media.Color.FromRgb(160, 180, 215);

            this.imgModel.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            this.imgModel.VerticalAlignment = System.Windows.VerticalAlignment.Center;

            this.UpdateTextures();
        }

        /// <summary>
        /// Returns a colored version of the input bitmap.
        /// </summary>
        /// <param name="bmpInput"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        private Bitmap ColorBitmap(Bitmap bmpInput, System.Windows.Media.Color c)
        {
            for (int h = 0; h < bmpInput.Height; h++)
            {
                for (int w = 0; w < bmpInput.Width; w++)
                {
                    System.Drawing.Color p = bmpInput.GetPixel(w, h);
                    if (p != System.Drawing.Color.FromArgb(0, 0, 0, 0))
                    {
                        if (p != System.Drawing.Color.FromArgb(255, 249, 249, 249))
                        {
                            bmpInput.SetPixel(w, h, System.Drawing.Color.FromArgb(
                                (p.R + c.R) / 2,
                                (p.G + c.G) / 2,
                                (p.B + c.B) / 2
                                ));
                        }
                        else
                        {
                            bmpInput.SetPixel(w, h, System.Drawing.Color.White);
                        }
                    }
                }
            }

            Bitmap bmpColored = new Bitmap(bmpInput.Width * 3, bmpInput.Height * 3);
            using (Graphics g = Graphics.FromImage(bmpColored))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                g.DrawImage(bmpInput, 0, 0, bmpColored.Width, bmpColored.Height);
            }

            if (bmpColored.Width > m_vLargestWidth)
                m_vLargestWidth = bmpColored.Width;
            if (bmpColored.Height > m_vLargestHeight)
                m_vLargestHeight = bmpColored.Height;

            return bmpColored;
        }

        /// <summary>
        /// Updates the model views textures.
        /// </summary>
        private void UpdateTextures()
        {
            //
            // Note to developers:
            // 
            // This is for designer mode viewing to allow the model viewer to render the model
            // without having to recompile the application.
            //
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                this.m_vEyeTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vEyeFile), this.m_vEyeColor);
                this.m_vEyeWhitesTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vEyeWhitesFile), this.m_vEyeWhitesColor);
                this.m_vHairTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vHairFile), this.m_vHairColor);
                this.m_vHandsTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vHandsFile), this.m_vHandsColor);
                this.m_vHeadTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vHeadFile), this.m_vHeadColor);
                this.m_vPantsTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vPantsFile), this.m_vPantsColor);
                this.m_vShirtTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vShirtFile), this.m_vShirtColor);
                this.m_vShoesTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vShoesFile), this.m_vShoesColor);
                this.m_vUnderShirtTexture = this.ColorBitmap(new Bitmap(@"C:\Users\atom0s\Desktop\tsge\tsge\bin\Debug\" + this.m_vUnderShirtFile), this.m_vUnderShirtColor);
            }
            else
            {
                this.m_vEyeTexture = this.ColorBitmap(new Bitmap(this.m_vEyeFile), this.m_vEyeColor);
                this.m_vEyeWhitesTexture = this.ColorBitmap(new Bitmap(this.m_vEyeWhitesFile), this.m_vEyeWhitesColor);
                this.m_vHairTexture = this.ColorBitmap(new Bitmap(this.m_vHairFile), this.m_vHairColor);
                this.m_vHandsTexture = this.ColorBitmap(new Bitmap(this.m_vHandsFile), this.m_vHandsColor);
                this.m_vHeadTexture = this.ColorBitmap(new Bitmap(this.m_vHeadFile), this.m_vHeadColor);
                this.m_vPantsTexture = this.ColorBitmap(new Bitmap(this.m_vPantsFile), this.m_vPantsColor);
                this.m_vShirtTexture = this.ColorBitmap(new Bitmap(this.m_vShirtFile), this.m_vShirtColor);
                this.m_vShoesTexture = this.ColorBitmap(new Bitmap(this.m_vShoesFile), this.m_vShoesColor);
                this.m_vUnderShirtTexture = this.ColorBitmap(new Bitmap(this.m_vUnderShirtFile), this.m_vUnderShirtColor);
            }

            // Draw the new full model based on the largest images dimensions.
            Bitmap bmpModel = new Bitmap(m_vLargestWidth, m_vLargestHeight);
            using (Graphics g = Graphics.FromImage(bmpModel))
            {
                g.DrawImage(this.m_vPantsTexture, 0, 0);
                g.DrawImage(this.m_vShoesTexture, 0, 0);
                g.DrawImage(this.m_vShirtTexture, 0, 0);
                g.DrawImage(this.m_vUnderShirtTexture, 0, 0);
                g.DrawImage(this.m_vHandsTexture, 0, 0);
                g.DrawImage(this.m_vHeadTexture, 0, 0);
                g.DrawImage(this.m_vHairTexture, 0, 0);
                g.DrawImage(this.m_vEyeWhitesTexture, 0, 0);
                g.DrawImage(this.m_vEyeTexture, 0, 0);
            }

            // Save the new bitmap to a memory stream..
            MemoryStream ms = new MemoryStream();
            bmpModel.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            // Obtain the BitmapImage of the bitmap to use as a data source..
            BitmapImage bmpImage = new BitmapImage();
            bmpImage.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
            bmpImage.BeginInit();
            bmpImage.StreamSource = ms;
            bmpImage.EndInit();

            // Set the model viewer image source..
            this.imgModel.Source = bmpImage;
        }

        /// <summary>
        /// Gets or sets the eye color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color EyeColor
        {
            get { return this.m_vEyeColor; }
            set { this.m_vEyeColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the eye whites color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color EyeWhitesColor
        {
            get { return this.m_vEyeWhitesColor; }
            set { this.m_vEyeWhitesColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the hair color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color HairColor
        {
            get { return this.m_vHairColor; }
            set { this.m_vHairColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the hands color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color HandsColor
        {
            get { return this.m_vHandsColor; }
            set { this.m_vHandsColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the head color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color HeadColor
        {
            get { return this.m_vHeadColor; }
            set { this.m_vHeadColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the pants color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color PantsColor
        {
            get { return this.m_vPantsColor; }
            set { this.m_vPantsColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the shirt color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color ShirtColor
        {
            get { return this.m_vShirtColor; }
            set { this.m_vShirtColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the shoes color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color ShoesColor
        {
            get { return this.m_vShoesColor; }
            set { this.m_vShoesColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the undershirt color of this model viewer.
        /// </summary>
        public System.Windows.Media.Color UnderShirtColor
        {
            get { return this.m_vUnderShirtColor; }
            set { this.m_vUnderShirtColor = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the eye model file of this model viewer.
        /// </summary>
        public String EyeFile
        {
            get { return this.m_vEyeFile; }
            set { this.m_vEyeFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the eye whites model file of this model viewer.
        /// </summary>
        public String EyeWhitesFile
        {
            get { return this.m_vEyeWhitesFile; }
            set { this.m_vEyeWhitesFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the hair model file of this model viewer.
        /// </summary>
        public String HairFile
        {
            get { return this.m_vHairFile; }
            set { this.m_vHairFile = value; this.UpdateTextures(); }
        }
        
        /// <summary>
        /// Gets or sets the hands model file of this model viewer.
        /// </summary>
        public String HandsFile
        {
            get { return this.m_vHandsFile; }
            set { this.m_vHandsFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the head model file of this model viewer.
        /// </summary>
        public String HeadFile
        {
            get { return this.m_vHeadFile; }
            set { this.m_vHeadFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the pants model file of this model viewer.
        /// </summary>
        public String PantsFile
        {
            get { return this.m_vPantsFile; }
            set { this.m_vPantsFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the shirt model file of this model viewer.
        /// </summary>
        public String ShirtFile
        {
            get { return this.m_vShirtFile; }
            set { this.m_vShirtFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the shoes model file of this model viewer.
        /// </summary>
        public String ShoesFile
        {
            get { return this.m_vShoesFile; }
            set { this.m_vShoesFile = value; this.UpdateTextures(); }
        }

        /// <summary>
        /// Gets or sets the undershirt model file of this model viewer.
        /// </summary>
        public String UnderShirtFile
        {
            get { return this.m_vUnderShirtFile; }
            set { this.m_vUnderShirtFile = value; this.UpdateTextures(); }
        }
    }
}
